<template>
  <div
    class="flex-1 overflow-auto focus:outline-none space-y-4"
    tabindex="0"
    v-bind="$attrs"
  >
    <main class="flex-1 relative">
      <!-- Highlight Panel -->
      <div
        class="gap-y-2 flex flex-col items-start lg:flex-row lg:items-center lg:justify-between"
      >
        <div class="flex-1 min-w-0 shrink-0">
          <!-- Summary -->
          <div class="flex items-center">
            <div>
              <div class="flex items-center">
                <h1
                  class="pb-2.5 text-xl font-bold leading-6 text-main truncate flex items-center gap-x-3"
                >
                  {{ database.databaseName }}

                  <ProductionEnvironmentV1Icon
                    :environment="environment"
                    :tooltip="true"
                    class="w-5 h-5"
                  />
                </h1>
              </div>
            </div>
          </div>
          <dl
            class="flex flex-col space-y-1 md:space-y-0 md:flex-row md:flex-wrap"
            data-label="bb-database-detail-info-block"
          >
            <dt class="sr-only">{{ $t("common.environment") }}</dt>
            <dd class="flex items-center text-sm md:mr-4">
              <span class="textlabel"
                >{{ $t("common.environment") }}&nbsp;-&nbsp;</span
              >
              <EnvironmentV1Name
                :environment="environment"
                icon-class="textinfolabel"
              />
            </dd>
            <dt class="sr-only">{{ $t("common.instance") }}</dt>
            <dd class="flex items-center text-sm md:mr-4">
              <span class="ml-1 textlabel"
                >{{ $t("common.instance") }}&nbsp;-&nbsp;</span
              >
              <InstanceV1Name :instance="database.instanceResource" />
            </dd>
            <dt class="sr-only">{{ $t("common.project") }}</dt>
            <dd class="flex items-center text-sm md:mr-4">
              <span class="textlabel"
                >{{ $t("common.project") }}&nbsp;-&nbsp;</span
              >
              <ProjectV1Name
                :project="database.projectEntity"
                hash="#databases"
              />
            </dd>
            <SQLEditorButtonV1
              class="text-sm md:mr-4"
              :database="database"
              :label="true"
              :disabled="!allowQuery"
              @failed="handleGotoSQLEditorFailed"
            />
            <SchemaDiagramButton
              v-if="hasSchemaDiagramFeature"
              class="md:mr-4"
              :database="database"
            />
          </dl>
        </div>
        <div
          v-if="allowToChangeDatabase"
          class="flex flex-row justify-start items-center flex-wrap shrink gap-x-2 gap-y-2"
          data-label="bb-database-detail-action-buttons-container"
        >
          <SyncDatabaseButton
            :type="'default'"
            :text="false"
            :database="database"
            @finish="updateAnomalyList"
          />
          <NButton
            v-if="allowTransferDatabase"
            @click.prevent="tryTransferProject"
          >
            <span>{{ $t("database.transfer-project") }}</span>
            <heroicons-outline:switch-horizontal
              class="-mr-1 ml-2 h-5 w-5 text-control-light"
            />
          </NButton>
          <NButton
            v-if="allowChangeData"
            @click="createMigration('bb.issue.database.data.update')"
          >
            <span>{{ $t("database.change-data") }}</span>
          </NButton>
          <NButton
            v-if="allowAlterSchema"
            @click="createMigration('bb.issue.database.schema.update')"
          >
            <span>{{ $t("database.edit-schema") }}</span>
          </NButton>
        </div>
      </div>
    </main>

    <NTabs v-model:value="state.selectedTab">
      <NTabPane name="overview" :tab="$t('common.overview')">
        <DatabaseOverviewPanel
          class="mt-2"
          :database="database"
          :anomaly-list="anomalyList"
        />
      </NTabPane>
      <NTabPane
        v-if="allowToChangeDatabase && allowListChangeHistories"
        name="change-history"
        :tab="$t('change-history.self')"
      >
        <DatabaseChangeHistoryPanel class="mt-2" :database="database" />
      </NTabPane>
      <NTabPane
        v-if="allowToChangeDatabase && allowListSlowQueries"
        name="slow-query"
        :tab="$t('slow-query.slow-queries')"
      >
        <DatabaseSlowQueryPanel class="mt-2" :database="database" />
      </NTabPane>
      <NTabPane
        v-if="allowToChangeDatabase"
        name="setting"
        :tab="$t('common.settings')"
      >
        <DatabaseSettingsPanel class="mt-2" :database="database" />
      </NTabPane>
    </NTabs>

    <BBModal
      v-if="state.showIncorrectProjectModal"
      :title="$t('common.warning')"
      @close="state.showIncorrectProjectModal = false"
    >
      <div class="col-span-1 w-96">
        {{ $t("database.incorrect-project-warning") }}
      </div>
      <div class="pt-6 flex justify-end space-x-3">
        <NButton @click.prevent="state.showIncorrectProjectModal = false">
          {{ $t("common.cancel") }}
        </NButton>
        <NButton
          type="primary"
          @click.prevent="
            state.showIncorrectProjectModal = false;
            state.showTransferDatabaseModal = true;
          "
        >
          {{ $t("database.go-to-transfer") }}
        </NButton>
      </div>
    </BBModal>
  </div>

  <Drawer
    :show="state.showTransferDatabaseModal"
    :auto-focus="true"
    @close="state.showTransferDatabaseModal = false"
  >
    <TransferOutDatabaseForm
      :database-list="[database]"
      :selected-database-names="[database.name]"
      @dismiss="state.showTransferDatabaseModal = false"
    />
  </Drawer>

  <SchemaEditorModal
    v-if="state.showSchemaEditorModal"
    :database-names="[database.name]"
    alter-type="SINGLE_DB"
    @close="state.showSchemaEditorModal = false"
  />
</template>

<script lang="ts" setup>
import { useTitle } from "@vueuse/core";
import dayjs from "dayjs";
import { NButton, NTabPane, NTabs } from "naive-ui";
import { computed, reactive, watch, ref, onMounted } from "vue";
import { useRouter } from "vue-router";
import { useRoute } from "vue-router";
import { BBModal } from "@/bbkit";
import SchemaEditorModal from "@/components/AlterSchemaPrepForm/SchemaEditorModal.vue";
import DatabaseChangeHistoryPanel from "@/components/Database/DatabaseChangeHistoryPanel.vue";
import DatabaseOverviewPanel from "@/components/Database/DatabaseOverviewPanel.vue";
import DatabaseSlowQueryPanel from "@/components/Database/DatabaseSlowQueryPanel.vue";
import { useDatabaseDetailContext } from "@/components/Database/context";
import {
  DatabaseSettingsPanel,
  SQLEditorButtonV1,
  SchemaDiagramButton,
} from "@/components/DatabaseDetail";
import SyncDatabaseButton from "@/components/DatabaseDetail/SyncDatabaseButton.vue";
import TransferOutDatabaseForm from "@/components/TransferOutDatabaseForm";
import { Drawer } from "@/components/v2";
import {
  EnvironmentV1Name,
  InstanceV1Name,
  ProductionEnvironmentV1Icon,
  ProjectV1Name,
} from "@/components/v2";
import { PROJECT_V1_ROUTE_DATABASE_DETAIL } from "@/router/dashboard/projectV1";
import { PROJECT_V1_ROUTE_ISSUE_DETAIL } from "@/router/dashboard/projectV1";
import {
  useAnomalyV1Store,
  useAppFeature,
  useCurrentUserIamPolicy,
  useDatabaseV1Store,
  useEnvironmentV1Store,
} from "@/store";
import {
  databaseNamePrefix,
  instanceNamePrefix,
} from "@/store/modules/v1/common";
import { UNKNOWN_PROJECT_NAME, unknownEnvironment } from "@/types";
import type { Anomaly } from "@/types/proto/v1/anomaly_service";
import { State } from "@/types/proto/v1/common";
import {
  instanceV1HasAlterSchema,
  isDatabaseV1Queryable,
  allowUsingSchemaEditor,
  extractProjectResourceName,
} from "@/utils";

const databaseHashList = [
  "overview",
  "change-history",
  "slow-query",
  "setting",
] as const;
export type DatabaseHash = (typeof databaseHashList)[number];
const isDatabaseHash = (x: any): x is DatabaseHash =>
  databaseHashList.includes(x);

interface LocalState {
  showTransferDatabaseModal: boolean;
  showIncorrectProjectModal: boolean;
  showSchemaEditorModal: boolean;
  currentProjectName: string;
  selectedIndex: number;
  selectedTab: DatabaseHash;
}

const props = defineProps<{
  projectId: string;
  instanceId: string;
  databaseName: string;
}>();

const router = useRouter();
const databaseV1Store = useDatabaseV1Store();

const state = reactive<LocalState>({
  showTransferDatabaseModal: false,
  showIncorrectProjectModal: false,
  showSchemaEditorModal: false,
  currentProjectName: UNKNOWN_PROJECT_NAME,
  selectedIndex: 0,
  selectedTab: "overview",
});
const route = useRoute();
const currentUserIamPolicy = useCurrentUserIamPolicy();
const anomalyList = ref<Anomaly[]>([]);
const {
  allowTransferDatabase,
  allowChangeData,
  allowAlterSchema,
  allowListChangeHistories,
  allowListSlowQueries,
} = useDatabaseDetailContext();
const disableSchemaEditor = useAppFeature(
  "bb.feature.issue.disable-schema-editor"
);

onMounted(async () => {
  anomalyList.value = await useAnomalyV1Store().fetchAnomalyList({
    database: database.value.name,
  });
});

watch(
  () => route.hash,
  (hash) => {
    const targetHash = hash.replace(/^#?/g, "") as DatabaseHash;
    if (isDatabaseHash(targetHash)) {
      state.selectedTab = targetHash;
    }
  },
  { immediate: true }
);

watch(
  () => state.selectedTab,
  (tab) => {
    router.replace({
      name: PROJECT_V1_ROUTE_DATABASE_DETAIL,
      hash: `#${tab}`,
      query: route.query,
    });
  }
);

const database = computed(() => {
  return databaseV1Store.getDatabaseByName(
    `${instanceNamePrefix}${props.instanceId}/${databaseNamePrefix}${props.databaseName}`
  );
});
const project = computed(() => database.value.projectEntity);

const allowToChangeDatabase = computed(() => {
  return currentUserIamPolicy.allowToChangeDatabaseOfProject(
    project.value.name
  );
});

const hasSchemaDiagramFeature = computed((): boolean => {
  return instanceV1HasAlterSchema(database.value.instanceResource);
});

const allowQuery = computed(() => {
  return isDatabaseV1Queryable(database.value);
});

const tryTransferProject = () => {
  state.currentProjectName = project.value.name;
  state.showTransferDatabaseModal = true;
};

const createMigration = async (
  type: "bb.issue.database.schema.update" | "bb.issue.database.data.update"
) => {
  if (type === "bb.issue.database.schema.update") {
    if (
      database.value.syncState === State.ACTIVE &&
      allowUsingSchemaEditor([database.value]) &&
      !disableSchemaEditor.value
    ) {
      state.showSchemaEditorModal = true;
      return;
    }
  }

  // Create a user friendly default issue name
  const issueNameParts: string[] = [];
  issueNameParts.push(`[${database.value.databaseName}]`);
  issueNameParts.push(
    type === "bb.issue.database.schema.update" ? `Edit schema` : `Change data`
  );
  const datetime = dayjs().format("@MM-DD HH:mm");
  const tz = "UTC" + dayjs().format("ZZ");
  issueNameParts.push(`${datetime} ${tz}`);

  const query: Record<string, any> = {
    template: type,
    name: issueNameParts.join(" "),
    databaseList: database.value.name,
  };

  router.push({
    name: PROJECT_V1_ROUTE_ISSUE_DETAIL,
    params: {
      projectId: extractProjectResourceName(project.value.name),
      issueSlug: "create",
    },
    query,
  });
};

const handleGotoSQLEditorFailed = () => {
  state.currentProjectName = database.value.project;
  state.showIncorrectProjectModal = true;
};

const updateAnomalyList = async () => {
  anomalyList.value = await useAnomalyV1Store().fetchAnomalyList({
    database: database.value.name,
  });
};

const environment = computed(() => {
  return (
    useEnvironmentV1Store().getEnvironmentByName(
      database.value.effectiveEnvironment
    ) ?? unknownEnvironment()
  );
});

useTitle(database.value.databaseName);
</script>
